home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1996
/
MacHack 1996.toast
/
Hacks
/
Hacks ’87
/
Source ƒ.sit
/
Source ƒ
/
C ƒ
/
CITADEL BBS 'C' SRC
/
CONFG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-01-14
|
43KB
|
1,287 lines
/************************************************************************/
/* confg.c */
/* configuration program for Citadel bulletin board system. */
/************************************************************************/
#include "ctdl.h"
/************************************************************************/
/* History */
/* */
/* 85Dec26 HAW Add CALL-LOG define. */
/* 85Nov15 HAW MS-DOS library update. */
/* 85Oct27 HAW Kill CERMETEK. */
/* 85Oct17 HAW Add paramVers, change bauds to array, searchBaud chg. */
/* 85Oct16 HAW Kill CLOCK, add officeStuff. */
/* 85Aug24 HAW Add duomessage file, NETDISK specification. */
/* 85Jul07 HAW Update so won't go through total recon. on init. */
/* 85May27 HAW Start stuffing in auto-networking stuff. */
/* 85May22 HAW Start conversion to make log file size sysop selectable.*/
/* 85May11 HAW Make "Lobby" sysop definable */
/* 85May06 HAW Add bail out code. */
/* 85May05 HAW Add helpDisk parameter for 3 disk system. */
/* 85Apr10 HAW Fix logSort, alphabetize file. */
/* 85Mar11 HAW Put all user functions in this file. */
/* 85Feb18 HAW Add baud search stuff. */
/* 85Jan20 HAW Use MSDOS #define for date stuff. */
/* 84Sep05 HAW Isolate strangeness in compiler's library. See note. */
/* 84Aug30 HAW Onwards to MS-DOS! */
/* 84Apr08 HAW Update to BDS C 1.50a begun. */
/* 82Nov20 CrT Created. */
/************************************************************************/
/************************************************************************/
/* Contents */
/* */
/* dGetWord() reads a word off disk */
/* init() system startup initialization */
/* main() main controller */
/* illegal() abort bottleneck */
/* getMessage() load message into RAM */
/* getMsgChar() returns successive chars off disk */
/* getMsgStr() reads a string out of message.buf */
/* msgInit() sets up cfg.catChar, catSect etc. */
/* startAt() setup to read a message off disk */
/* unGetMsgChar() return a char to getMsgChar() */
/* zapMsgFile() initialize ctdlmsg.sys */
/* realZap() does work of zapMsgFile() */
/* indexRooms() build RAM index to ctdlroom.sys */
/* noteRoom() enter room into RAM index */
/* zapRoomFile() erase & re-initialize ctdlroom.sys */
/* setSpace() set default disk and user# */
/* hash() hashes a string to an integer */
/* logInit() builds the RAM index to CTDLLOG.SYS */
/* noteLog() enters a userlog record into RAM index */
/* sortLog() sort CTDLLOG by time since last call */
/* wrapup() finishes and writes ctdlTabl.sys */
/* zapLogFile() erases & re-initializes CTDLLOG.SYS */
/************************************************************************/
/************************************************************************/
/* Strangenesses (Hue, Jr., 12Sep84) */
/* Have discovered that the line: */
/* sscanf(line, "\"%s\"", str); */
/* is not parsed the same way by this compiler as it is by BDS; */
/* this is highly unfortunate and excrable. So, all porters */
/* should note that scanf() is not, in any way, "portable." If */
/* BDS is "non-standard", then the standard sucks. */
/************************************************************************/
/************************************************************************/
/* External variable declarations in CONFG.C */
/************************************************************************/
extern struct config cfg; /* The configuration variable */
static unsigned char GMCCache; /* To unGetMsgChar() into */
struct msgB msgBuf; /* The -sole- message buffer */
extern struct netBuffer netBuf;
FILE *msgfl; /* file descriptor for the msg file */
static int thisChar; /* next char in sectBuf */
static unsigned thisSector; /* next sector in msgfl */
static int oldChar; /* Old value of thisChar */
static unsigned oldSector; /* Old value of thisSector */
static unsigned char sectBuf[SECTSIZE];
/* ^ msgfl sector buffer (simulated) */
extern struct rTable roomTab[MAXROOMS]; /* RAM index of rooms */
extern struct aRoom roomBuf; /* room buffer */
extern FILE *roomfl; /* file descriptor for rooms */
extern int thisRoom; /* room currently in roomBuf */
extern struct logBuffer logBuf; /* Log buffer of a person */
extern struct lTable *logTab; /* RAM index of pippuls */
extern int thisLog; /* entry currently in logBuf */
extern FILE *logfl; /* log file descriptor */
extern FILE *netfl;
char *baseRoom;
extern struct netTable *netTab;
extern int thisNet;
long mailCount=0;
char msgZap = FALSE,
logZap = FALSE,
roomZap = FALSE;
/************************************************************************/
/* External function definitions for CONFG.C */
/************************************************************************/
extern FILE *fopen();
char toUpper();
unsigned char getMsgChar();
int fread();
long fseek();
char *malloc();
/************************************************************************/
/* init() -- master system initialization */
/************************************************************************/
init(attended)
int attended;
{
unsigned char c;
unsigned i;
char *msgFile, *netFile, *roomFile, *logFile;
cfg.sizeLTentry = sizeof(*logTab);
cfg.debug = FALSE;
cfg.noChat = TRUE;
/* shave-and-a-haircut/two bits pause pattern for ringing sysop: */
cfg.shave[0] = 40;
cfg.shave[1] = 20;
cfg.shave[2] = 20;
cfg.shave[3] = 40;
cfg.shave[4] = 80;
cfg.shave[5] = 40;
cfg.shave[6] =250;
/* initialize input character-translation table: */
for (c = 0; c < '\40'; c++) {
cfg.filter[c] = '\0'; /* control chars -> nulls */
}
for (c='\40'; c < 128; c++) {
cfg.filter[c] = c; /* pass printing chars */
}
cfg.filter[SPECIAL] = SPECIAL;
cfg.filter[CNTRLl] = CNTRLl;
cfg.filter[DEL ] = BACKSPACE;
cfg.filter[BACKSPACE] = BACKSPACE;
cfg.filter[XOFF ] = 'P' ;
cfg.filter['\r' ] = NEWLINE ;
cfg.filter[CNTRLO ] = 'N' ;
setSpace(cfg.homeDisk, "");
msgFile = "a:ctdlmsg.sys";
*msgFile += cfg.msgDisk;
netFile = "a:ctdlnet.sys";
*netFile += cfg.netDisk;
roomFile = "a:ctdlroom.sys";
*roomFile += cfg.sysDisk;
logFile = "a:ctdllog.sys";
*logFile += cfg.sysDisk;
/* open message file */
if ((netfl = fopen(netFile, "rb")) == NULL) {
printf(" %s not found, creating new file.\n", netFile);
if ((netfl = fopen(netFile, "wb")) == NULL)
illegal("?Can't create the net file!");
}
if ((msgfl = fopen(msgFile, "rwb")) == NULL) {
if (!attended)
illegal("!System must be attended for creation!");
printf(" %s not found, creating new file. \n", msgFile);
if ((msgfl = fopen(msgFile, "wrb")) == NULL)
illegal("?Can't create the message file!");
printf(" (Be sure to initialize it!)\n");
}
/* open room file */
if ((roomfl = fopen(roomFile, "rwb")) == NULL) {
if (!attended)
illegal("!System must be attended for creation!");
printf(" %s not found, creating new file. \n", roomFile);
if ((roomfl = fopen(roomFile, "wrb")) == NULL)
illegal("?Can't create room file!");
printf(" (Be sure to initialize it!)\n");
}
/* open userlog file */
if ((logfl = fopen(logFile, "rwb")) == NULL) {
if (!attended)
illegal("!System must be attended for creation!");
printf(" %s not found, creating new file. \n", logFile);
if ((logfl = fopen(logFile, "wrb")) == NULL)
illegal("?Can't create log file!");
printf(" (Be sure to initialize it!)\n");
}
printf("\n Erase and initialize log, message and/or room files?");
if (attended)
if (toUpper(getch()) == 'Y') {
/* each of these has an additional go/no-go interrogation: */
msgZap = zapMsgFile();
roomZap = zapRoomFile();
logZap = zapLogFile();
}
}
/************************************************************************/
/* main() for confg.c */
/************************************************************************/
main(argc, argv)
int argc;
char **argv;
{
FILE *fBuf, *pwdfl;
char line[90];
char cmd[90], var[90], string[90];
int arg, arg2, args;
int i, j, offset = 0;
union {
int *pi;
unsigned char *pc;
} nextCode; /* where to deposit next code */
cfg.paramVers = 6;
printf("Citadel-86 Configurator (V%d)\n\n", cfg.paramVers);
cfg.sysPassword[0] = 0;
cfg.weAre = CONFIGUR;
cfg.MAXLOGTAB = 0; /* Initialize, just in case */
if ((fBuf = fopen("ctdlcnfg.sys", "r")) == NULL) { /* ASCII mode */
printf("?Can't find ctdlCnfg.sys!\n");
exit();
}
nextCode.pc = &cfg.codeBuf[0];
while (fgets(line, 90, fBuf) != NULL) {
if (args = sscanf(line, "%s %s %x ", cmd, var, &arg)) {
if (strCmp(cmd, "#define" ) == SAMESTRING && args == 3) {
printf("#define '%s' as %x\n", var, arg);
if (strCmp(var, "MEGAHZ" ) == SAMESTRING) {
cfg.megaHz = arg;
} else if (strCmp(var, "CRYPTSEED" ) == SAMESTRING) {
cfg.cryptSeed = arg;
#ifndef MSDOS
} else if (strCmp(var, "CLOCK" ) == SAMESTRING) {
cfg.clock = arg;
#endif
} else if (strCmp(var, "MESSAGEK" ) == SAMESTRING) {
cfg.maxMSector = arg*8;
} else if (strCmp(var, "MSGDISK" ) == SAMESTRING) {
cfg.msgDisk = arg;
} else if (strCmp(var, "HOMEDISK" ) == SAMESTRING) {
cfg.homeDisk = arg;
} else if (strCmp(var, "SYSDISK" ) == SAMESTRING) {
cfg.sysDisk = arg;
} else if (strCmp(var, "NETDISK" ) == SAMESTRING) {
cfg.netDisk = arg;
} else if (strCmp(var, "LOGINOK" ) == SAMESTRING) {
cfg.unlogLoginOk= arg;
} else if (strCmp(var, "ENTEROK" ) == SAMESTRING) {
cfg.unlogEnterOk= arg;
} else if (strCmp(var, "READOK" ) == SAMESTRING) {
cfg.unlogReadOk = arg;
} else if (strCmp(var, "ROOMOK" ) == SAMESTRING) {
cfg.nonAideRoomOk=arg;
} else if (strCmp(var, "ALLMAIL" ) == SAMESTRING) {
cfg.noMail = !arg;
} else if (strCmp(var, "SEARCHBAUD") == SAMESTRING) {
cfg.search_baud = arg;
} else if (strCmp(var, "IBM" ) == SAMESTRING) {
cfg.IBM_or_clone= arg;
} else if (strCmp(var, "COM" ) == SAMESTRING) {
if (arg == 1) {
cfg.modem_data = 0x3f8;
cfg.modem_status = 0x3fd;
cfg.line_status = 0x3fd;
}
else if (arg == 2) {
cfg.modem_data = 0x2f8;
cfg.modem_status = 0x2fd;
cfg.line_status = 0x2fd;
}
else illegal("COM port can only currently be 1 or 2");
} else if (strCmp(var, "TIMEOUT" ) == SAMESTRING) {
cfg.dailyTimeout= arg;
} else if (strCmp(var, "HOUROUT" ) == SAMESTRING) {
if ((cfg.hourOut = arg) > 23 || arg < 0)
illegal("Illegal value: 0 <= HOUROUT <= 23");
} else if (strCmp(var, "MIRRORMSG" ) == SAMESTRING) {
cfg.mirror = arg;
} else if (strCmp(var, "MSG2DISK" ) == SAMESTRING) {
cfg.mbkpDisk = arg;
} else if (strCmp(var, "LOGSIZE" ) == SAMESTRING) {
cfg.MAXLOGTAB = arg;
logTab = (struct lTable *) malloc(sizeof(*logTab) * arg);
} else if (strCmp(var, "NETWORK" ) == SAMESTRING) {
cfg.netParticipant = arg;
} else if (strCmp(var, "LONG-HAUL" ) == SAMESTRING) {
cfg.longHaul = arg;
} else if (strCmp(var, "DAYDIV" ) == SAMESTRING) {
cfg.dayDiv = arg;
} else if (strCmp(var, "NETHOUR" ) == SAMESTRING) {
cfg.netHour = arg;
} else if (strCmp(var, "NETLENGTH" ) == SAMESTRING) {
cfg.netLength = arg;
} else if (strCmp(var, "SYSBAUD" ) == SAMESTRING) {
cfg.sysBaud = arg;
if (arg > 3 || arg < 0) {
illegal(
"Valid SYSBAUD values: 0=300, 1=3/12, 2=3/12/24, 3=3/12/24/Your option");
}
} else if (strCmp(var, "CALL-LOG" ) == SAMESTRING) {
cfg.call_log = arg;
} else {
printf("? -- no variable '%s' known! -- ignored.\n", var);
}
} else if (strCmp(cmd, "#start" ) == SAMESTRING) {
printf("#start procedure '%s'\n", var);
if (strCmp(var, "HANGUP" ) == SAMESTRING) {
cfg.pHangUp = offset;
} else if (strCmp(var, "INITPORT" ) == SAMESTRING) {
cfg.pInitPort = offset;
} else if (strCmp(var, "CARRDETECT") == SAMESTRING) {
cfg.pCarrDetect = offset;
} else if (strCmp(var, "MIREADY" ) == SAMESTRING) {
cfg.pMIReady = offset;
} else if (strCmp(var, "MOREADY" ) == SAMESTRING) {
cfg.pMOReady = offset;
} else if (strCmp(var, "SET300" ) == SAMESTRING) {
cfg.pBauds[ONLY_300] = offset;
} else if (strCmp(var, "SET1200" ) == SAMESTRING) {
cfg.pBauds[BOTH_300_1200] = offset;
} else if (strCmp(var, "SET2400" ) == SAMESTRING) {
cfg.pBauds[TH_3_12_24] = offset;
} else if (strCmp(var, "SET_HIGHER") == SAMESTRING) {
cfg.pBauds[SetYourOwn] = offset;
} else if (strCmp(var, "CHECKBAUD" ) == SAMESTRING) {
cfg.pCheckBaud = offset;
#ifndef MSDOS
} else if (strCmp(var, "INITDATE" ) == SAMESTRING) {
cfg.pInitDate = offset;
} else if (strCmp(var, "GETDAY" ) == SAMESTRING) {
cfg.pGetDay = offset;
} else if (strCmp(var, "GETMONTH" ) == SAMESTRING) {
cfg.pGetMonth = offset;
} else if (strCmp(var, "GETYEAR" ) == SAMESTRING) {
cfg.pGetYear = offset;
#endif
} else printf("?--no procedure '%s' known!\n", var);
} else if (strCmp(cmd, "#code" ) == SAMESTRING) {
printf("#code '%s'\n", var);
if (strCmp(var, "LOAD" ) == SAMESTRING) {
*nextCode.pc++ = LOAD;
*nextCode.pi++ = arg;
offset += 3;
} else if (strCmp(var, "ANDI" ) == SAMESTRING) {
*nextCode.pc++ = ANDI;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "ORI" ) == SAMESTRING) {
*nextCode.pc++ = ORI;
*nextCode.pc++ =arg;
offset += 2;
} else if (strCmp(var, "XORI" ) == SAMESTRING) {
*nextCode.pc++ = XORI;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "STORE" ) == SAMESTRING) {
*nextCode.pc++ = STORE;
*nextCode.pi++ = arg;
offset += 3;
} else if (strCmp(var, "LOADI" ) == SAMESTRING) {
*nextCode.pc++ = LOADI;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "RET" ) == SAMESTRING) {
*nextCode.pc++ = RET;
offset++;
} else if (strCmp(var, "INP" ) == SAMESTRING) {
*nextCode.pc++ = INP;
*nextCode.pi++ = arg;
offset += 3;
} else if (strCmp(var, "OUTP" ) == SAMESTRING) {
*nextCode.pc++ = OUTP;
*nextCode.pi++ = arg;
offset += 3;
} else if (strCmp(var, "PAUSEI" ) == SAMESTRING) {
*nextCode.pc++ = PAUSEI;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "ARRAY[]=" ) == SAMESTRING) {
*nextCode.pc++ = STOREX;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "ARRAY[]" ) == SAMESTRING) {
*nextCode.pc++ = LOADX;
*nextCode.pc++ = arg;
offset += 2;
} else if (strCmp(var, "OPR#" ) == SAMESTRING) {
*nextCode.pc++ = OPRNUMBER;
offset++;
/* reparse to pick up string: */
sscanf(line, "%s %s \"%s\" %d %d",
cmd, var, string, &arg, &arg2
);
/* BDS was excellent. C86 sucks. Reparse by hand <sigh>: */
for (i = strLen(line) - 1; line[i] != '"'; i--)
;
sscanf(line + ++i, " %d %d", &arg, &arg2);
string[strLen(string) - 1] = '\0'; /* Bug kludge */
/* copy string into code buffer: */
strCpy(nextCode.pc, string);
while (*nextCode.pc++) /* step over string */
offset++;
offset++;
*nextCode.pc++ = arg; /* lower limit */
*nextCode.pc++ = arg2; /* upper limit */
offset += 2;
} else if (strCmp(var, "OUTSTRING" ) == SAMESTRING) {
*nextCode.pc++ = OUTSTRING;
offset++;
/* reparse to pick up string: */
/* sscanf(line, "%s %s \"%s\"", cmd, var, string); */
/* Reparse on our own (stupid scanf() function, it worked in BDS!): */
readString(line, nextCode.pc, TRUE);
while (*nextCode.pc++) /* step over string */
offset++;
offset++;
nextCode.pc--;
*nextCode.pc++ = '\r'; /* add a CR */
*nextCode.pc++ = '\0'; /* tie off with null */
offset++;
} else printf("?--no code '%s'!\n", var);
} else if (strCmp(cmd, "#nodeTitle") == SAMESTRING) {
readString(line, nextCode.pc, TRUE);
cfg.nodeTitle = offset;
while (*nextCode.pc++) /* step over string */
offset++;
offset++; /* I don't know why, but it works */
} else if (strCmp(cmd, "#sysPassword") == SAMESTRING) {
readString(line, cfg.sysPassword, FALSE);
if ((pwdfl = fopen(cfg.sysPassword, "r")) == NULL)
printf("\nNo system password file found\n");
else {
fgets(cfg.sysPassword, 199, pwdfl);
cfg.sysPassword[strLen(cfg.sysPassword) - 1] = 0;
if (strLen(cfg.sysPassword) < 15) {
printf("\nSystem password is too short -- ignored\n");
cfg.sysPassword[0] = 0;
}
fclose(pwdfl);
}
} else if (strCmp(cmd, "#callOutSuffix") == SAMESTRING) {
readString(line, nextCode.pc, TRUE);
cfg.netSuffix = offset;
while (*nextCode.pc++) /* step over string */
offset++;
offset++; /* I don't know why, but it works */
} else if (strCmp(cmd, "#callOutPrefix") == SAMESTRING) {
readString(line, nextCode.pc, TRUE);
cfg.netPrefix = offset;
while (*nextCode.pc++) /* step over string */
offset++;
offset++; /* I don't know why, but it works */
} else if (strCmp(cmd, "#nodeName" ) == SAMESTRING) {
readString(line, nextCode.pc, FALSE);
if (strLen(nextCode.pc) > 19)
illegal("nodeName too long; must be less than 20");
cfg.nodeName = offset;
while (*nextCode.pc++) /* step over string */
offset++;
offset++; /* I don't know why, but it works */
} else if (strCmp(cmd, "#nodeId" ) == SAMESTRING) {
readString(line, nextCode.pc, FALSE);
if (strLen(nextCode.pc) > 19)
illegal("nodeId too long; must be less than 20");
cfg.nodeId = offset;
while (*nextCode.pc++) /* step over string */
offset++;
offset++; /* I don't know why, but it works */
} else if (strCmp(cmd, "#baseRoom") == SAMESTRING) {
readString(line, nextCode.pc, TRUE);
if (strLen(nextCode.pc) > 19)
illegal("baseRoom too long; must be less than 20");
cfg.bRoom = offset;
baseRoom = nextCode.pc;
while (*nextCode.pc++)
offset++;
offset++;
} else if (strCmp(cmd, "#alldone") == SAMESTRING) {
break;
} else if (cmd[0] == '#') printf("? -- no '%s' command!\n", cmd);
}
}
if (nextCode.pc < &cfg.codeBuf[MAXCODE]) {
init(!(argc - 1));
wrapup();
} else {
illegal(
"\7codeBuf[] overflow! Recompile with larger MAXCODE or reduce ctdlCnfg.sys\7"
);
}
}
/***********************************************************************/
/* readString() reads a '#<id> "<value>" since scanf can't */
/***********************************************************************/
readString(source, destination, doProc)
char *source, *destination;
char doProc;
{
char string[300], last = 0;
int i, j;
for (i = 0; source[i] != '"'; i++)
;
for (j = 0, i++; source[i] != '"' || last == '\\'; i++, j++) {
string[j] = source[i];
last = source[i];
}
string[j] = '\0';
strCpy(destination, string);
if (doProc) xlatfmt(destination);
}
/************************************************************************/
/* isoctal() xlatfmt() -- contributed by Dale Schumacher, allow */
/* embedding of formatting info a la' "C" style: \n, \t, etc.... */
/************************************************************************/
isoctal( c )
int c;
{
return(( c >= '0' ) && ( c <= '7' ));
}
xlatfmt( s )
char *s;
{
register char *p, *q;
register int i;
for( p=q=s; *q; ++q ) {
if ( *q == '\\' )
switch( *++q ) {
case 'n' :
*p++ = '\n';
break;
case 't' :
*p++ = '\t';
break;
case 'b' :
*p++ = '\b';
break;
case 'r' :
*p++ = '\r';
break;
case 'f' :
*p++ = '\f';
break;
default :
if ( isoctal( *q )) {
i = (( *q++ ) - '0' );
if ( isoctal( *q )) {
i <<= 3;
i += (( *q++ ) - '0' );
if ( isoctal( *q )) {
i <<= 3;
i += (*q -'0');
}
else
--q;
}
else
--q;
*p++ = 0xFF & ((char) i);
}
else
*p++ = *q;
break;
}
else
*p++ = *q;
}
*p = '\0';
return( s );
}
/***********************************************************************/
/* illegal() Prints out configur error message and aborts */
/***********************************************************************/
illegal(errorstring)
char *errorstring;
{
printf("\007\nERROR IN CONFIGURATION:\n%s\nABORTING", errorstring);
exit(7);
}
/************************************************************************/
/* dGetWord() fetches one word from current message, off disk */
/* returns TRUE if more words follow, else FALSE */
/************************************************************************/
char dGetWord(dest, lim)
char *dest;
int lim;
{
char c;
--lim; /* play it safe */
/* pick up any leading blanks: */
for (c = getMsgChar(); c == ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
/* step through word: */
for ( ; c != ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
/* trailing blanks: */
for ( ; c == ' ' && c && lim; c = getMsgChar()) {
if (lim) { *dest++ = c; lim--; }
}
if (c) unGetMsgChar(c); /* took one too many */
*dest = '\0'; /* tie off string */
return c;
}
/************************************************************************/
/* getMessage() reads a message off disk into RAM. */
/* a previous call to setUp has specified the message. */
/************************************************************************/
getMessage()
{
unsigned char c;
/* clear msgBuf out */
msgBuf.mbauth[ 0] = '\0';
msgBuf.mbdate[ 0] = '\0';
msgBuf.mborig[ 0] = '\0';
msgBuf.mboname[0] = '\0';
msgBuf.mbroom[ 0] = '\0';
msgBuf.mbsrcId[0] = '\0';
msgBuf.mbtext[ 0] = '\0';
msgBuf.mbto[ 0] = '\0';
msgBuf.mbaddr[ 0] = '\0';
do c = getMsgChar(); while (c != 0xFF); /* find start of msg */
msgBuf.mbheadChar = oldChar; /* record location */
msgBuf.mbheadSector = oldSector;
getMsgStr(msgBuf.mbId, NAMESIZE);
do {
c = getMsgChar();
switch (c) {
case 'A': getMsgStr(msgBuf.mbauth, NAMESIZE); break;
case 'D': getMsgStr(msgBuf.mbdate, NAMESIZE); break;
case 'M': /* just exit -- we'll read off disk */ break;
case 'N': getMsgStr(msgBuf.mboname, NAMESIZE); break;
case 'O': getMsgStr(msgBuf.mborig, NAMESIZE); break;
case 'R': getMsgStr(msgBuf.mbroom, NAMESIZE); break;
case 'S': getMsgStr(msgBuf.mbsrcId, NAMESIZE); break;
case 'T': getMsgStr(msgBuf.mbto, NAMESIZE); break;
case 'Q': getMsgStr(msgBuf.mbaddr, NAMESIZE); break;
default:
getMsgStr(msgBuf.mbtext, MAXTEXT); /* discard unknown field */
msgBuf.mbtext[0] = '\0';
break;
}
} while (c != 'M' && isAlpha(c));
if (strCmpU(msgBuf.mbroom, "Mail") == SAMESTRING) mailCount++;
}
/************************************************************************/
/* getMsgChar() returns sequential chars from message on disk */
/************************************************************************/
unsigned char getMsgChar()
{
char toReturn;
if (GMCCache) { /* someone did an unGetMsgChar() --return it */
toReturn= GMCCache;
GMCCache= '\0';
return toReturn;
}
oldChar = thisChar;
oldSector = thisSector;
toReturn = sectBuf[thisChar];
#ifdef XYZZY
if (debug) putCh(visible(toReturn));
#endif
thisChar = ++thisChar % SECTSIZE;
if (thisChar == 0) {
/* time to read next sector in: */
thisSector = ++thisSector % cfg.maxMSector;
fseek(msgfl, (long) thisSector * SECTSIZE, 0);
if (fread(sectBuf, SECTSIZE, 1, msgfl) != 1) {
exit(printf("?nextMsgChar-read fail"));
}
crypte(sectBuf, SECTSIZE, 0);
}
return(toReturn);
}
/************************************************************************/
/* getMsgStr() reads a string from message.buf */
/************************************************************************/
getMsgStr(dest, lim)
char *dest;
int lim;
{
char c;
while (c = getMsgChar()) { /* read the complete string */
if (lim) { /* if we have room then */
lim--;
*dest++ = c; /* copy char to buffer */
}
}
*dest = '\0'; /* tie string off with null */
}
/************************************************************************/
/* msgInit() sets up lowId, highId, cfg.catSector and cfg.catChar, */
/* by scanning over message.buf */
/************************************************************************/
msgInit()
{
int atoi();
ulong first, here;
startAt(0, 0);
getMessage();
/* get the ID# */
sscanf(msgBuf.mbId, "%ld", &first);
printf("message# %lu\n", first);
cfg.newest = cfg.oldest = first;
cfg.catSector = thisSector;
cfg.catChar = thisChar;
for (getMessage();
sscanf(msgBuf.mbId, "%ld", &here), here != first;
getMessage()) {
printf("message# %lu\n", here);
/* find highest and lowest message IDs: */
if (here < cfg.oldest) {
cfg.oldest = here;
printf(" oldest=%lu\n", cfg.oldest);
}
if (here > cfg.newest) {
cfg.newest = here;
printf(" newest=%lu\n", cfg.newest);
/* read rest of message in and remember where it ends, */
/* in case it turns out to be the last message */
/* in which case, that's where to start writing next message*/
while (dGetWord(msgBuf.mbtext, MAXTEXT));
cfg.catSector = thisSector;
cfg.catChar = thisChar;
}
}
}
/************************************************************************/
/* startAt() sets location to begin reading message from */
/************************************************************************/
startAt(sect, byt)
unsigned sect;
int byt;
{
GMCCache = '\0'; /* cache to unGetMsgChar() into */
if (sect >= cfg.maxMSector) {
printf("?startAt s=%d,b=%d", sect, byt);
printf("?startAt crash");
exit();
}
thisChar = byt;
thisSector = sect;
fseek(msgfl, SECTSIZE * sect, 0);
if (fread(sectBuf, SECTSIZE, 1, msgfl) != 1) {
printf("?startAt read fail");
}
crypte(sectBuf, SECTSIZE, 0);
}
/************************************************************************/
/* unGetMsgChar() returns (at most one) char to getMsgChar() */
/************************************************************************/
unGetMsgChar(c)
unsigned char c;
{
GMCCache = c;
}
/************************************************************************/
/* zapMsgFl() initializes message.buf */
/************************************************************************/
zapMsgFile()
{
label fn;
printf("\nDestroy all current messages? ");
if (toUpper(getch()) != 'Y') return FALSE;
if (cfg.mirror) printf("Creating primary message file.\n");
realZap();
if (cfg.mirror) {
fclose(msgfl);
strCpy(fn, "a:ctdlmsg.sys");
fn[0] += cfg.mbkpDisk;
if ((msgfl = fopen(fn, "wrb")) == NULL)
illegal("?Can't create the secondary message file!");
printf("Creating secondary message file.\n");
realZap();
}
return TRUE;
}
/************************************************************************/
/* realZap() does work of zapMsgFile */
/************************************************************************/
realZap()
{
int i;
unsigned sect;
/* put null message in first sector... */
sectBuf[0] = 0xFF; /* \ */
sectBuf[1] = '1'; /* > Message ID "1" MS-DOS style */
sectBuf[2] = '\0'; /* / */
sectBuf[3] = 'M'; /* \ Null messsage */
sectBuf[4] = '\0'; /* / */
cfg.newest = cfg.oldest = 1l;
cfg.catSector = 0;
cfg.catChar = 5;
for (i=5; i<SECTSIZE; i++) sectBuf[i] = 0;
crypte(sectBuf, SECTSIZE, 0); /* encrypt */
if (fwrite(sectBuf, SECTSIZE, 1, msgfl) != 1) {
printf("zapMsgFil: write failed\n");
}
crypte(sectBuf, SECTSIZE, 0); /* decrypt */
sectBuf[0] = 0;
crypte(sectBuf, SECTSIZE, 0); /* encrypt */
printf("\n%d sectors to be cleared\n", cfg.maxMSector);
for (sect = 1l; sect < cfg.maxMSector; sect++) {
printf("%u\r", sect);
if (fwrite(sectBuf, SECTSIZE, 1, msgfl) != 1) {
printf("zapMsgFil: write failed\n");
}
}
crypte(sectBuf, SECTSIZE, 0); /* decrypt */
return TRUE;
}
/************************************************************************/
/* indexRooms() -- build RAM index to CTDLROOM.SYS, displays stats.*/
/************************************************************************/
indexRooms()
{
int goodRoom, m, roomCount, slot;
roomCount = 0;
for (slot = 0; slot < MAXROOMS; slot++) {
getRoom(slot);
printf("Checking room #%d: ", slot);
if (roomBuf.rbflags.INUSE == 1) {
roomBuf.rbflags.INUSE = 0; /* clear "inUse" flag */
for (m = 0, goodRoom = FALSE; m < MSGSPERRM && !goodRoom; m++) {
if (roomBuf.msg[m].rbmsgNo > cfg.oldest) {
goodRoom = TRUE;
}
}
if (goodRoom || roomBuf.rbflags.PERMROOM == 1) {
roomBuf.rbflags.INUSE = 1;
}
if (roomBuf.rbflags.INUSE == 1) {
if (slot == 0) /* Ugly kludge */
strCpy(roomBuf.rbname, baseRoom);
roomCount++;
}
else {
zero_struct(roomBuf.rbflags);
/* roomBuf.rbflags.INUSE = 0;
roomBuf.rbflags.MSDOSDIR = 0;
roomBuf.rbflags.PERMROOM = 0;
roomBuf.rbflags.INUSE = 0; */
}
}
printf("%s\n",
(roomBuf.rbflags.INUSE == 1) ? roomBuf.rbname : "<not in use>");
noteRoom();
putRoom(slot);
}
printf(" %d of %d rooms in use\n", roomCount, MAXROOMS);
}
/************************************************************************/
/* noteRoom() -- enter room into RAM index array. */
/************************************************************************/
noteRoom()
{
int i;
ulong last;
last = 0l;
for (i = 0; i < MSGSPERROOM; i++) {
if (roomBuf.msg[i].rbmsgNo > cfg.newest) {
roomBuf.msg[i].rbmsgNo = 0l;
}
if (roomBuf.msg[i].rbmsgNo > last) {
last = roomBuf.msg[i].rbmsgNo;
}
}
roomTab[thisRoom].rtlastMessage = last ;
strCpy(roomTab[thisRoom].rtname, roomBuf.rbname) ;
roomTab[thisRoom].rtgen = roomBuf.rbgen ;
copy_struct(roomBuf.rbflags, roomTab[thisRoom].rtflags);
/* roomTab[thisRoom].rtflags.INUSE = roomBuf.rbflags.INUSE;
roomTab[thisRoom].rtflags.PUBLIC = roomBuf.rbflags.PUBLIC;
roomTab[thisRoom].rtflags.MSDOSDIR = roomBuf.rbflags.MSDOSDIR;
roomTab[thisRoom].rtflags.PERMROOM = roomBuf.rbflags.PERMROOM;
roomTab[thisRoom].rtflags.SKIP = roomBuf.rbflags.SKIP;
roomTab[thisRoom].rtflags.UPLOAD = roomBuf.rbflags.UPLOAD;
roomTab[thisRoom].rtflags.DOWNLOAD = roomBuf.rbflags.DOWNLOAD;
roomTab[thisRoom].rtflags.SHARED = roomBuf.rbflags.SHARED; */
}
/************************************************************************/
/* zapRoomFile() erases and re-initailizes CTDLROOM.SYS */
/************************************************************************/
zapRoomFile()
{
int i;
printf("\nWipe room file? ");
if (toUpper(getch()) != 'Y') return FALSE;
printf("\n");
zero_struct(roomBuf.rbflags);
/* roomBuf.rbflags.INUSE = FALSE;
roomBuf.rbflags.PUBLIC = FALSE;
roomBuf.rbflags.MSDOSDIR = FALSE;
roomBuf.rbflags.PERMROOM = FALSE;
roomBuf.rbflags.SKIP = FALSE; */
roomBuf.rbgen = 0;
roomBuf.rbdisk = 0;
roomBuf.rbdirname[0] = 0;
roomBuf.rbname[0] = 0; /* unnecessary -- but I like it... */
for (i = 0; i < MSGSPERRM; i++) {
roomBuf.msg[i].rbmsgNo = 0l;
roomBuf.msg[i].rbmsgLoc = 0 ;
}
printf("maxrooms=%d\n", MAXROOMS);
for (i = 0; i < MAXROOMS; i++) {
printf("clearing room %d\n", i);
putRoom(i);
noteRoom();
}
/* Lobby> always exists -- guarantees us a place to stand! */
thisRoom = 0 ;
strCpy(roomBuf.rbname, baseRoom) ;
roomBuf.rbflags.PERMROOM = TRUE;
roomBuf.rbflags.PUBLIC = TRUE;
roomBuf.rbflags.INUSE = TRUE;
putRoom(LOBBY);
noteRoom();
/* Mail> is also permanent... */
thisRoom = MAILROOM ;
strCpy(roomBuf.rbname, "Mail") ;
/* Don't bother to copy flags, they remain the same (right?) */
putRoom(MAILROOM);
noteRoom();
/* Aide> also... */
thisRoom = AIDEROOM ;
strCpy(roomBuf.rbname, "Aide") ;
roomBuf.rbflags.PERMROOM = TRUE;
roomBuf.rbflags.PUBLIC = FALSE;
roomBuf.rbflags.INUSE = TRUE;
putRoom(AIDEROOM);
noteRoom();
return TRUE;
}
/************************************************************************/
/* setSpace() moves us to a disk and user# */
/************************************************************************/
#define SETDISK 14
setSpace(disk, dir)
char disk;
char *dir;
{
bdos(SETDISK, disk);
cfg.ourDisk = disk;
if (strCmp(dir, "") == SAMESTRING) {
strCpy(cfg.ourUser, "..");
}
else {
strCpy(cfg.ourUser, dir);
if (chdir(dir) == EOF) {
printf("?Directory not present!\n ");
setSpace(cfg.homeDisk, "");
return FALSE;
}
}
return TRUE;
}
/************************************************************************/
/* hash() hashes a string to an integer */
/************************************************************************/
int hash(str)
char *str;
{
int h, i, shift;
for (h=shift=0; *str; shift=(shift+1)&7, str++) {
h ^= (i=toUpper(*str)) << shift;
}
return h;
}
/************************************************************************/
/* logInit() indexes ctdllog.sys */
/************************************************************************/
logInit()
{
int i;
int logSort();
int count = 0;
long rewind();
if (rewind(logfl) != 0l) illegal("Rewinding logfl failed!");
/* clear logTab */
for (i = 0; i < cfg.MAXLOGTAB; i++) logTab[i].ltnewest = 0l;
/* load logTab: */
for (thisLog = 0; thisLog < cfg.MAXLOGTAB; thisLog++) {
printf("log#%3d", thisLog);
getLog(&logBuf, thisLog);
/* count valid entries: */
if (logBuf.lbflags.L_INUSE == 1) {
count++;
printf(" %s", logBuf.lbname);
}
else printf(" <not in use>");
printf("\n");
/* copy relevant info into index: */
logTab[thisLog].ltnewest = logBuf.lbvisit[0];
logTab[thisLog].ltlogSlot= thisLog;
if (logBuf.lbflags.L_INUSE == 1) {
logTab[thisLog].ltnmhash = hash(logBuf.lbname);
logTab[thisLog].ltpwhash = hash(logBuf.lbpw );
}
else {
logTab[thisLog].ltnmhash = 0;
logTab[thisLog].ltpwhash = 0;
}
}
printf(" logInit--%d valid log entries\n", count);
printf("sortLog...\n");
qsort(logTab, cfg.MAXLOGTAB, cfg.sizeLTentry, logSort);
}
/************************************************************************/
/* logSort() Sorts 2 entries in logTab */
/************************************************************************/
int logSort(s1, s2)
struct lTable *s1, *s2;
{
if (s1->ltnmhash == 0 && s2->ltnmhash == 0)
return 0;
if (s1->ltnmhash == 0 && s2->ltnmhash != 0)
return 1;
if (s1->ltnmhash != 0 && s2->ltnmhash == 0)
return -1;
if (s1->ltnewest < s2->ltnewest)
return 1;
if (s1->ltnewest > s2->ltnewest)
return -1;
return 0;
}
/************************************************************************/
/* noteLog() notes logTab entry in RAM buffer in master index */
/************************************************************************/
noteLog()
{
int i, slot;
/* figure out who it belongs between: */
for (i = 0; logTab[i].ltnewest > logBuf.lbvisit[0]; i++);
/* note location and open it up: */
slot = i;
slideLTab(slot, cfg.MAXLOGTAB-1);
/* insert new record */
logTab[slot].ltnewest = logBuf.lbvisit[0] ;
logTab[slot].ltlogSlot = thisLog ;
logTab[slot].ltpwhash = hash(logBuf.lbpw) ;
logTab[slot].ltnmhash = hash(logBuf.lbname);
}
/************************************************************************/
/* slideLTab() slides bottom N lots in logTab down. For sorting. */
/************************************************************************/
slideLTab(slot, last)
int slot;
int last;
{
int i;
/* open slot up: (movmem isn't guaranteed on overlaps) */
for (i = last - 1; i >= slot; i--) {
movmem(&logTab[i], &logTab[i + 1], cfg.sizeLTentry);
}
}
/************************************************************************/
/* wrapup() finishes up and writes ctdlTabl.sys out, finally */
/************************************************************************/
wrapup()
{
printf("\ncreating ctdlTabl.sys table\n");
if (!msgZap) msgInit();
if (!roomZap) indexRooms();
cfg.weAre = CITADEL;
if (!logZap) logInit();
netInit();
fclose(netfl);
fclose(roomfl);
fclose(msgfl);
fclose(logfl);
printf("%ld of the messages were Mail\n", mailCount);
printf("writeSysTab = %d\n", writeSysTab());
}
/************************************************************************/
/* zapLogFile() erases & re-initializes userlog.buf */
/************************************************************************/
zapLogFile()
{
int i;
printf("\nWipe out log file? ");
if (toUpper(getch()) != 'Y') return FALSE;
printf("\n");
/* clear RAM buffer out: */
logBuf.lbflags.L_INUSE = FALSE;
for (i = 0; i < MAILSLOTS; i++) {
logBuf.lbslot[i] = 0l;
logBuf.lbId[i] = 0l;
}
for (i = 0; i < NAMESIZE; i++) {
logBuf.lbname[i] = 0;
logBuf.lbpw[i] = 0;
}
/* write empty buffer all over file; */
for (i = 0; i < cfg.MAXLOGTAB; i++) {
printf("Clearing log #%d\n", i);
putLog(&logBuf, i);
logTab[i].ltnewest = logBuf.lbvisit[0];
logTab[i].ltlogSlot= i;
logTab[i].ltnmhash = hash(logBuf.lbname);
logTab[i].ltpwhash = hash(logBuf.lbpw );
}
return TRUE;
}
getch()
{
return bdos(7);
}
/************************************************************************/
/* netInit() Initialize RAM index for net */
/************************************************************************/
netInit()
{
label temp;
int i = 0;
cfg.netSize = (int) ((fseek(netfl, -1l, 2) + 1) / sizeof (netBuf));
netTab = (struct netTable *) malloc(sizeof (*netTab) * cfg.netSize);
while (i < cfg.netSize) {
getNet(i);
normId(netBuf.netId, temp);
netTab[i].ntnmhash = hash(netBuf.netName);
netTab[i].ntidhash = hash(temp);
netTab[i].ntflags.in_use = netBuf.nbflags.in_use;
netTab[i].ntflags.normal_mail = netBuf.nbflags.normal_mail;
netTab[i].ntflags.room_files = netBuf.nbflags.room_files;
printf("System %3d. %s\n", i,
(netBuf.nbflags.in_use) ? netBuf.netName : "<not in use>");
i++;
}
}
/************************************************************************/
/* strCmpU() is strcmp(), but ignoring case distinctions */
/************************************************************************/
int strCmpU(s, t)
char s[], t[];
{
int i;
i = 0;
while (toUpper(s[i]) == toUpper(t[i])) {
if (s[i++] == '\0') return 0;
}
return toUpper(s[i]) - toUpper(t[i]);
}
/************************************************************************/
/* normId() Normalizes a node id. */
/************************************************************************/
normId(source, dest)
label source, dest;
{
while (!isalpha(*source) && *source)
source++;
if (!*source) return FALSE;
*dest++ = toUpper(*source++);
while (!isalpha(*source) && *source)
source++;
if (!*source) return FALSE;
*dest++ = toUpper(*source++);
while (*source) {
if (isdigit(*source))
*dest++ = *source;
source++;
}
*dest = '\0';
return TRUE;
}
/************************************************************************/
/* crashout() fatal error, for library functions */
/************************************************************************/
crashout(str)
char *str;
{
illegal(str);
}